Technical Q&A
HW 49 - Detecting specific ROM-in-RAM Mac (29-Mar-99)
Q: All ROM-in-RAM (New World) Macs return
406 (decimal) as their machine ID from Gestalt . How do I
determine which Mac my software is running on in this case?
A: You will have to query the Name Registry to
get this information.
|
Important: Do not attempt to infer if a feature exists by
checking the machine ID. Use the Name Registry or
Gestalt to determine if a specific feature
exists. If checking the machine ID is the only way to
determine if a specific feature exists, file a bug report with
us so that we can fix that.
|
You can get the Mac’s non-localized name from the compatible
property. The value is an array of C-style strings, and the name is
the first entry of the property’s value. The compatible property is
found at the path “Devices:device-tree”. For the ‘99 Power Macintosh
G3 this value is “PowerMac1,1”. For the iMac this value is
“iMac,1”.
|
Note: This string is not meant to be shown to the user.
It is not localized. Do not show this string to the
user.
|
Because these strings are not localized, you can easily test them;
just don’t show them to the user.
|
Note: Currently, all iMacs have the same compatible
property value: “iMac,1”.
|
To tell the difference between the original iMac with the Rage II
video chip and the second revision of the iMac with the Rage Pro
video chip, you can look for a Name Registry node of
“Devices:device-tree:pci:ATY,RageIIC_C” or
“Devices:device-tree:pci:ATY,RagePro_C”, respectively. You can also
search for a node with a name property of “ATY,RageIIC_C” or
“ATY,RagePro_C”, respectively. Either method will work with equal
effectiveness.
To tell the difference between the 233MHz iMac with a Rage Pro
video chip and the 266MHz iMac (which also has a Rage Pro video
chip), you will need to check the clock-frequency property in the
cpu node. The best way to do this is to search for a node with a
device_type property with the value of “cpu\0” (the null terminator
of the C string needs to be passed; it is part of the property’s
value). Once you have found the node with the cpu value, you can get
the value of the clock-frequency property which is in the same
node. You cannot just search for “clock-frequency” because there are
many “clock-frequency” entries in the Name Registry and you are not
guaranteed that the “clock-frequency” value you get is the one from
the cpu node.
|
Important: I hope that the above serves
to show how strongly we suggest that you do not try
to identify specific Macs. Instead you should look for
specific features (via Gestalt , or some other
means) that you need, such as FireWire or USB, rather than
assuming that they are present based solely on the model of
the computer.
You should always check for what you
want, rather than assume a specific machine always has the
feature you want. If you believe that you cannot check for a
specific feature and are therefore relying on the machine
ID, please file a bug with us so that we can
have a selector added.
|
/* GetMacName returns a c formatted (null terminated string with the
* model property string.
* Input macName - pointer to a buffer where the model property name
* will be returned, if the call succeeds
*
* Output function result - noErr indicates that the model name was
* read successfully
* macName - will contain the model name property if noErr
*
* Notes:
* Caller is responsible for disposing of macName. Use DisposePtr.
*/
OSStatus GetMacName (StringPtr * macName) {
OSStatus err = noErr;
RegEntryID compatibleEntry;
RegPropertyValueSize length;
RegCStrEntryNamePtr compatibleValue;
if (macName != nil) {
*macName = 0;
err = RegistryEntryIDInit (&compatibleEntry);
if (err == noErr) {
err = RegistryCStrEntryLookup (nil, "Devices:device-tree", &compatibleEntry);
}
if (err == noErr) {
err = RegistryPropertyGetSize (&compatibleEntry, "compatible", &length);
}
if (err == noErr) {
compatibleValue = (RegCStrEntryNamePtr)NewPtr (length);
err = MemError ();
}
if (err == noErr) {
err = RegistryPropertyGet (&compatibleEntry, "compatible", compatibleValue, &length);
}
if (err == noErr) {
SetPtrSize (compatibleValue, strlen (compatibleValue) + 1);
/* SetPtrSize shouldn't fail because we are shrinking the pointer, but make sure. */
err = MemError ();
}
if (err == noErr) {
*macName = c2pstr (compatibleValue);
}
(void)RegistryEntryIDDispose (&compatibleEntry);
}
return err;
}
/* GetMacSpeed returns the clock-frequency property of the cpu
* Output function result - noErr indicates that the cpu clock-frequency
* property was read successfully
* cpuFreq - will contain the clock-frequency property if noErr
* set to 0 if the clock-frequency could not be read
*/
OSStatus GetMacSpeed (UInt32 * cpuFreq) {
OSStatus err = noErr;
RegEntryID cpuEntry;
RegEntryIter cookie = nil;
RegEntryIterationOp iterOp = kRegIterDescendants;
unsigned long cpuSpeedSize = sizeof (unsigned long);
char * cpuValue = "cpu";
Boolean done;
if (cpuFreq != nil) {
*cpuFreq = 0;
} else {
cpuSpeedSize = 0;
}
if (err == noErr) {
err = RegistryEntryIDInit (&cpuEntry);
}
if (err == noErr) {
err = RegistryEntryIterateCreate (&cookie);
}
if (err == noErr) {
err = RegistryEntrySearch (&cookie, iterOp, &cpuEntry, &done, "device_type",
cpuValue, strlen (cpuValue) + 1);
if (done != true && err == noErr) {
(void)RegistryPropertyGet (&cpuEntry, "clock-frequency", cpuFreq, &cpuSpeedSize);
}
}
(void)RegistryEntryIDDispose (&cpuEntry);
(void)RegistryEntryIterateDispose (&cookie);
return err;
}
|
This is some sample code that shows how to query the Name Registry
for the name and clock frequency values.
-- Mark Cookson
Worldwide Developer Technical Support
Technical Q&As | Contents
Previous Question | Next Question
To contact us, please use the Contact Us page.
|